package com.zyk.scaffold.user.mail;

import com.alibaba.fastjson.JSON;
import com.zyk.scaffold.common.utils.StringUtils;
import com.zyk.scaffold.user.mail.enums.MailTypeEnum;
import com.zyk.scaffold.user.mail.properties.ApiConfig;
import com.zyk.scaffold.user.mail.properties.LocalMailProperties;
import com.zyk.scaffold.user.mail.properties.MailServer;
import com.zyk.scaffold.user.mail.sender.ILocalMailSender;
import com.zyk.scaffold.user.mail.sender.LocalMailApiSender;
import com.zyk.scaffold.user.mail.sender.LocalMailServerSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "local.mail", name = "send-email")
public class AccountMailSenderManager {

    private Map<String, ILocalMailSender> senderMapping = new HashMap();
    private LocalMailProperties localMailProperties;
    private String defaultName;

    public AccountMailSenderManager(@Autowired LocalMailProperties localMailProperties) {
        if (localMailProperties == null || CollectionUtils.isEmpty(localMailProperties.getMailServers())) {
            log.error("邮件账号配置为空");
            return;
        }
        this.localMailProperties = localMailProperties;
        List<MailServer> mailServers = localMailProperties.getMailServers();
        for (MailServer mailServer : mailServers) {
            if (StringUtils.isEmpty(defaultName)) {
                defaultName = mailServer.getName();
            }
            ILocalMailSender sender = buildMailSender(mailServer);
            if (sender != null) {
                senderMapping.put(mailServer.getName(), sender);
            }
        }
        log.info("邮件账号sender初始化完毕：" + JSON.toJSONString(localMailProperties));
    }

    private ILocalMailSender buildMailSender(MailServer mailServer) {
        ILocalMailSender sender = null;
        String type = mailServer.getType();
        if (MailTypeEnum.MAIL_TYPE_SERVER_SMTP.getCode().equals(type)) {
            MailProperties mailConfig = mailServer.getMailConfig();
            if (mailConfig != null) {
                JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
                applyProperties(mailServer.getMailConfig(), javaMailSender);
                sender = new LocalMailServerSender(javaMailSender, mailServer.getName(), this.localMailProperties);
            }
        }
        if (MailTypeEnum.MAIL_TYPE_API.getCode().equals(type)) {
            ApiConfig apiConfig = mailServer.getApiConfig();
            if (apiConfig != null) {
                sender = new LocalMailApiSender(apiConfig);
            }
        }
        return sender;
    }

    public ILocalMailSender getMailSender(String name) {
        if (StringUtils.isEmpty(name)) {
            name = defaultName;
        }
        ILocalMailSender sender = senderMapping.get(name);
        if (sender == null) {
            return senderMapping.get(defaultName);
        }
        return sender;
    }

    private void applyProperties(MailProperties properties, JavaMailSenderImpl sender) {
        sender.setHost(properties.getHost());
        if (properties.getPort() != null) {
            sender.setPort(properties.getPort());
        }
        sender.setUsername(properties.getUsername());
        sender.setPassword(properties.getPassword());
        sender.setProtocol(properties.getProtocol());
        if (properties.getDefaultEncoding() != null) {
            sender.setDefaultEncoding(properties.getDefaultEncoding().name());
        }
        if (!properties.getProperties().isEmpty()) {
            sender.setJavaMailProperties(asProperties(properties.getProperties()));
        }
    }

    private Properties asProperties(Map<String, String> source) {
        Properties properties = new Properties();
        properties.putAll(source);
        return properties;
    }
}
